#include <thread>
#include <sys/stat.h>

#include "ExtendHub.h"
#include "Protocol.h"

const std::string ExtendHub::OK{"_OK"};


using namespace std::chrono_literals;

ExtendHub::ExtendHub(DummyChannel& channel, const ExtendDeviceType& deviceType, const std::string& deviceActknowlege) : ExtendDevice(channel, deviceType, deviceActknowlege) {
    //ctor
}

ExtendHub::~ExtendHub() {
    //dtor
}



bool ExtendHub::updateFirmware(const std::filesystem::path& filename) {
    bool result = true;
    std::string resultString;
    std::string errorMessage;
    std::string command{"<UPDATEFIRMWARE_"};
    std::string firmwareName = filename.filename();
    try {
        BasicDevice fileDevice(filename);
        struct stat statbuff;
        if (fileDevice && 0 == fstat(fileDevice.getDeviceFd(), &statbuff)) {
            firmwareName += BINARY_TO_CHAR(statbuff.st_size);
            command += firmwareName;
            command += '>';
            mchannel.sendStringReturnString(command, resultString);
            if (std::string::npos != resultString.find(OK, command.size() - 1)) {

                ssize_t readed;
                constexpr uint16_t length = sizeof (FirmwareDataHeader_t) + DATA_SLICE_SIZE;
                std::string buffer(length, '\0');
                FirmwareDataHeader_t* pDataHeader = reinterpret_cast <FirmwareDataHeader_t*>(&buffer[0]);
                pDataHeader->headTag = 0xffffffff;
                uint8_t i = 0;
                do {
                    pDataHeader->order = i;
                    readed = ::read(fileDevice.getDeviceFd(), pDataHeader->payload,  DATA_SLICE_SIZE);
                    if (0 < readed) {
                        buffer.resize(sizeof (FirmwareDataHeader_t) + readed);

                        mchannel.sendStringReturnString(buffer, resultString);
                        if (buffer != resultString) {
                            for (int retryCount = 0; retryCount < 255 && buffer != resultString; ++retryCount) {
                                mchannel.sendStringReturnString(buffer, resultString);
                            }
                        }


//                        mchannel.write(buffer);
//                        std::this_thread::sleep_for(200ms);
                    }
                    ++i;
                } while(0 < readed);
                if (0 == readed) {
                    command = "<FINISHUPDATEFIRMWARE_";
                    command += firmwareName;
                    command += '>';
                    mchannel.sendStringReturnString(command, resultString);
                    if (std::string::npos == resultString.find(OK, command.size() - 1)) {
                        result = false;
                    }
                }

            } else {
                result = false;
                errorMessage = resultString + " is not ok";
            }
        } else {
            result = false;
            errorMessage = filename;
            errorMessage +=  " not found!";
        }

        if (!result) {
            LOG_DEDUG("updateFirmware failed:%s", errorMessage.data());
        } else {
            std::this_thread::sleep_for(20ms);
            recheck();
        }
    } catch (std::exception& ex) {
        LOG_ERROR("updateFirmware failed:%s", ex.what());
    }

    return result;
}



